package cn.cdeden.knowledge.service.impl;

import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.mybatis.validator.QueryHelpMybatisPlus;
import cn.cdeden.common.oss.enumd.OssBucketOneEnum;
import cn.cdeden.common.oss.enumd.OssModuleType;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.knowledge.domain.FilesDistributeSender;
import cn.cdeden.knowledge.domain.PersonalFilesTree;
import cn.cdeden.knowledge.domain.dto.FileUserDto;
import cn.cdeden.knowledge.domain.dto.FilesDistributeTreeDto;
import cn.cdeden.knowledge.domain.dto.FilesDistributeTreeQueryParam;
import cn.cdeden.knowledge.domain.dto.TeamFilesTreeDto;
import cn.cdeden.knowledge.domain.vo.FilesSizeType;
import cn.cdeden.knowledge.domain.vo.PersonalFilesTreeVo;
import cn.cdeden.knowledge.enums.FileEnums;
import cn.cdeden.knowledge.enums.TreeTypeEnum;
import cn.cdeden.knowledge.service.FileService;
import cn.cdeden.knowledge.service.PersonalFilesTreeService;
import cn.cdeden.knowledge.service.TeamService;
import cn.cdeden.resource.api.RemoteFileService;
import cn.cdeden.resource.api.domain.RemoteFile;
import cn.cdeden.system.api.RemoteUserService;
import cn.cdeden.system.api.domain.vo.RemoteUserVo;
import cn.cdeden.system.api.model.LoginUser;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import io.undertow.util.BadRequestException;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.cdeden.knowledge.mapper.FilesDistributeTreeMapper;
import cn.cdeden.knowledge.domain.FilesDistributeTree;
import cn.cdeden.knowledge.service.FilesDistributeTreeService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = FilesDistributeTreeService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class FilesDistributeTreeServiceImpl extends ServiceImpl<FilesDistributeTreeMapper, FilesDistributeTree> implements FilesDistributeTreeService{

    private final FilesDistributeTreeMapper filesDistributeTreeMapper;

    private final PersonalFilesTreeService personalFilesTreeService;

    private final TeamService teamService;

    private final FileService fileService;

    @DubboReference(check = false)
    private final RemoteUserService remoteUserService;

    @DubboReference(check = false)
    private final RemoteFileService remoteFileService;

    @Override
    public void copyToPersonalLibByTreeVo(String distributeId, String specifyParentId) throws BadRequestException {
        QueryWrapper<FilesDistributeTree> predicate = QueryHelpMybatisPlus.getPredicate(new FilesDistributeTreeQueryParam());
        predicate.eq("distribute_id", distributeId);
        predicate.isNull("parent_id");
        List<FilesDistributeTreeDto> list = MapstructUtils.convert(filesDistributeTreeMapper.selectList(predicate), FilesDistributeTreeDto.class);
        List<String> collect = new ArrayList<>();
        for (FilesDistributeTreeDto filesDistributeTreeDto : list) {
            Long id = filesDistributeTreeDto.getId();
            collect.add(String.valueOf(id));
        }
        LoginUser user = LoginHelper.getLoginUser();
        RemoteUserVo remoteUserVo = remoteUserService.selectUserByUserId(user.getUserId());
        FileUserDto fileUserDto = new FileUserDto();
        fileUserDto.setId(remoteUserVo.getUserId());
        fileUserDto.setUsername(remoteUserVo.getUserName());
        fileUserDto.setMinioBucket(remoteUserVo.getMinioBucket());

        Long total = personalFilesTreeService.folderCheck(collect);
        if (remoteUserService.upperLimit(String.valueOf(user.getUserId()), total)) {
            throw new BadRequestException("超出个人文件存储上线 删除回收站数据或者联系管理员添加空间");
        }
        for (int i = 0; i < list.size(); i++) {
            FilesDistributeTreeDto filesDistributeTreeDto = list.get(i);
            setChildren(MapstructUtils.convert(list.get(i), PersonalFilesTree.class), specifyParentId, String.valueOf(list.get(i).getId()), fileUserDto);
//            setChildren(ConvertUtil.convert(list.get(i), PersonalFilesTree.class), specifyParentId, String.valueOf(list.get(i).getId()), user);
        }
    }

    @Override
    public FilesDistributeTree insertByPersonalFilesTreeVo(PersonalFilesTreeVo personalFilesTreeVo, Integer distributeId) {
        FilesDistributeTree entity = MapstructUtils.convert(personalFilesTreeVo, FilesDistributeTree.class);
//        FilesDistributeTree entity = ConvertUtil.convert(personalFilesTreeVo, FilesDistributeTree.class);
        entity.setModules(FileEnums.PERSONAL_FILE.getCode());
        if (entity.getType().equals("file")) {
            //TODO 如果是文件，就放到minio的临时桶中(等待文件上传接口完成)
//            //如果是文件，就放到minio的临时桶中
//            FileUserDto user = FileUserUtils.getUser();
//            Storage copy = fileStorageUtils.copy(String.valueOf(user.getId()), user.getUsername(), FileEnums.TEMPORARY_FILE, StorageFolderTypeEnum.TEMPORARY_FILES.getCode(), personalFilesTreeVo.getStorageId(), null, null);
//            entity.setStorageId(Long.toString(copy.getStorageId()));
//            entity.setEdition(copy.getEdition());
//            entity.setEditionName(copy.getEditionName());
//            entity.setFileMd5(copy.getFileMd5());
        }
        entity.setDistributeId(String.valueOf(distributeId));
        entity.setId(null);
        filesDistributeTreeMapper.insert(entity);
        List<PersonalFilesTreeVo> children = personalFilesTreeVo.getChildren();
        for (int i = 0; i < children.size(); i++) {
            PersonalFilesTreeVo childrenPersonalFilesTreeVo = children.get(i);
            childrenPersonalFilesTreeVo.setParentId(String.valueOf(entity.getId()));
            insertByPersonalFilesTreeVo(childrenPersonalFilesTreeVo, distributeId);
        }

        return entity;
    }

    @Override
    public FilesDistributeTree insertByTeamFilesTree(TeamFilesTreeDto teamFilesTrees, Integer distributeId) {
        FilesDistributeTree entity = MapstructUtils.convert(teamFilesTrees, FilesDistributeTree.class);
        entity.setModules(FileEnums.TEAM_FILE.getCode());
        if (entity.getType().equals("file")) {
            //如果是文件，就放到minio的临时桶中
            RemoteFile remoteFile = new RemoteFile();
            remoteFile.setOssId(Long.valueOf(teamFilesTrees.getStorageId()));
            RemoteFile copy = remoteFileService.copyFile(remoteFile,teamService.getById(teamFilesTrees.getTeamId()).getMinioBucket(), OssModuleType.Team);
            entity.setStorageId(Long.toString(copy.getOssId()));
            entity.setEdition(copy.getVersionId());
            entity.setEditionName(copy.getVersionName());
//            Storage copy = fileStorageUtils.copy(String.valueOf(user.getId()), user.getUsername(), FileEnums.TEMPORARY_FILE, StorageFolderTypeEnum.TEMPORARY_FILES.getCode(), teamFilesTrees.getStorageId(), null, null);
//            entity.setStorageId(Long.toString(copy.getStorageId()));
//            entity.setEdition(copy.getEdition());
//            entity.setEditionName(copy.getEditionName());
//            entity.setFileMd5(copy.getFileMd5());
        }
        entity.setDistributeId(String.valueOf(distributeId));
        entity.setId(null);
        filesDistributeTreeMapper.insert(entity);
        List<TeamFilesTreeDto> children = teamFilesTrees.getChildren();
        for (TeamFilesTreeDto childrenTeamFilesTreeDto : children) {
            childrenTeamFilesTreeDto.setParentId(String.valueOf(entity.getId()));
            insertByTeamFilesTree(childrenTeamFilesTreeDto, distributeId);
        }

        return entity;
    }

    /**
     * @param entity              树节点对象
     * @param specifyParentId     目标上级文件夹id
     * @param distributeTreeOldId 分发树里储存的id（用于找到分发树里的下级文件）
     */
    private void setChildren(PersonalFilesTree entity, String specifyParentId, String distributeTreeOldId, FileUserDto user) throws BadRequestException {
        String id = String.valueOf(entity.getId());
        PersonalFilesTree parentPersonalFilesTree = personalFilesTreeService.getById(specifyParentId);
        String type = parentPersonalFilesTree.getType();
        if (!type.equals(TreeTypeEnum.FOLDER.getType()) && !type.equals(TreeTypeEnum.HEAD.getType())){
            throw new BadRequestException("上级不为文件夹！");
        }
        entity.setId(null);
        entity.setCreateId(String.valueOf(LoginHelper.getUserId()));
//        entity.setCreateId(String.valueOf(FileUserUtils.getUser().getId()));
        entity.setParentId(specifyParentId);
        entity.setSuperiorsPath(parentPersonalFilesTree.getPath());
        String superiorsIds = parentPersonalFilesTree.getSuperiorsIds();
        if (StringUtils.isBlank(superiorsIds)) {
            superiorsIds = specifyParentId;
        } else {
            superiorsIds += "," + specifyParentId;
        }
        entity.setSuperiorsIds(superiorsIds);
        entity.setTopParentId(parentPersonalFilesTree.getTopParentId());
        //删除用户信息
//        entity.setCreateBy(null);
//        entity.setCreateId(null);
//        entity.setCreateTime(null);
//        entity.setUpdateBy(null);
//        entity.setUpdateTime(null);
//        entity.setUpdateId(null);

//        entity.setSuperiorsIds();
        if (entity.getType().equals("file")) {
            //如果是文件，就放到minio的临时桶中
            RemoteFile remoteFile = new RemoteFile();
            remoteFile.setOssId(Long.valueOf(entity.getStorageId()));
            RemoteFile copy = remoteFileService.copyFile(remoteFile, user.getMinioBucket(), OssModuleType.Personal);
//            Storage copy = fileStorageUtils.copy(String.valueOf(user.getId()), user.getUsername(), FileEnums.PERSONAL_FILE, user.getMinioBucket(), entity.getStorageId(), null, null);
            entity.setStorageId(Long.toString(copy.getOssId()));
            entity.setEdition(copy.getVersionId());
            entity.setEditionName(copy.getVersionName());
//            entity.setFileMd5(copy.get);
        }
        //检查 是否重命名
        String realName = entity.getRealName();

        Boolean aBoolean = personalFilesTreeService.judgeIsEmpty(String.valueOf(user.getId()), user.getUsername(), realName,
            specifyParentId, entity.getType(), entity.getSuffix());
        if (!aBoolean) {
            realName += "_" + "分发接收_" + System.currentTimeMillis();
        }
        entity.setRealName(realName);
        entity.setPath(parentPersonalFilesTree.getPath() + "/" + realName);
        boolean save = personalFilesTreeService.save(entity);

        //修改用户使用文件大小
        fileService.upDateFolderSizeUpDate(entity.getCreateId(), entity, null, entity.getSize(), FilesSizeType.AddSize); //复制

        List<PersonalFilesTree> children = getChildrenTree(distributeTreeOldId);
        for (PersonalFilesTree childrenPersonalFilesTree : children) {
            childrenPersonalFilesTree.setParentId(String.valueOf(entity.getId()));
            setChildren(childrenPersonalFilesTree, String.valueOf(entity.getId()), String.valueOf(childrenPersonalFilesTree.getId()), user);
        }
    }


    private List<PersonalFilesTree> getChildrenTree(String parentId) {
        QueryWrapper<FilesDistributeTree> predicate = QueryHelpMybatisPlus.getPredicate(new FilesDistributeTreeQueryParam());
        predicate.eq("parent_id", parentId);
        return MapstructUtils.convert(filesDistributeTreeMapper.selectList(predicate), PersonalFilesTree.class);
//        return ConvertUtil.convertList(filesDistributeTreeMapper.selectList(predicate), PersonalFilesTree.class);
    }


}
